﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Media.Imaging;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel.Presentation;
using CardPlay.Presentation.Drawing;

namespace CardPlay.Presentation
{
    public class Graphics : IGraphics
    {
        private readonly Image _facesImage;
        private readonly Image _background;
        private readonly Size _tileSize = new Size(144, 194);
        private readonly Size _cropSize = new Size(2, 2);

        public Graphics()
        {
            _facesImage = Resources.CardGraphics;
            _background = Resources.Background;

            var cardSize = _tileSize - _cropSize - _cropSize;
            CardSize = new System.Windows.Size(cardSize.Width, cardSize.Height);
        }

        public System.Windows.Size CardSize
        {
            get; set;
        }

        public BitmapSource CreateBackground()
        {
            var bitmap = new Bitmap(_background.Width, _background.Height, PixelFormat.Format24bppRgb);

            using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
            {
                graphics.DrawImage(_background, 0, 0);
            }

            return bitmap.ToBitmapSource();
        }

        public BitmapSource CreateEmptyCue(EmptyPileCue emptyCue)
        {
            return CreateEmptyCueBitmap(emptyCue).ToBitmapSource();
        }

        public BitmapSource CreateImageForCard(Card card)
        {
            return (card.IsFaceUp ? CreateCardFaceBitmap(card) : CreateCardBackBitmap(card.BackDesign)).ToBitmapSource();
        }

        public BitmapSource CreateCardFace(CardFace face)
        {
            return CreateCardFaceBitmap(face).ToBitmapSource();
        }

        private Bitmap CreateCardBackBitmap(int design)
        {
            return CreateBitmap(() => CardBackToBounds(design));
        }

        private Bitmap CreateCardFaceBitmap(CardFace face)
        {
            return CreateBitmap(() => CardFaceToBounds(face));
        }

        private Bitmap CreateEmptyCueBitmap(EmptyPileCue emptyCue)
        {
            return CreateBitmap(() => EmptyCueToBounds(emptyCue));
        }

        private Bitmap CreateBitmap(Func<Rectangle> boundsFunc)
        {
            var cardSize = new Size((int) CardSize.Width, (int) CardSize.Height);
            var bitmap = new Bitmap(cardSize.Width, cardSize.Height, PixelFormat.Format32bppArgb);

            using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
            {
                var bounds = boundsFunc();
                bounds.Inflate(-_cropSize.Width, -_cropSize.Height);
                graphics.DrawImage(_facesImage, new Rectangle(Point.Empty, cardSize), bounds, GraphicsUnit.Pixel);
            }

            return bitmap;
        }

        private Rectangle CardFaceToBounds(CardFace face)
        {
            var cardSize = _tileSize;

            var row =
                face.Suit == Suit.Spades ? 0 :
                face.Suit == Suit.Hearts ? 1 :
                face.Suit == Suit.Clubs ? 2 : 3;

            var origin = new Point(((int) face.Rank - 1) * cardSize.Width, row * cardSize.Height);
            return new Rectangle(origin, cardSize);
        }

        private Rectangle CardBackToBounds(int design)
        {
            var cardSize = _tileSize;

            var origin = new Point(design * cardSize.Width, 8 * cardSize.Height);
            return new Rectangle(origin, cardSize);
        }

        private Rectangle EmptyCueToBounds(EmptyPileCue emptyCue)
        {
            var cardSize = _tileSize;

            var origin = new Point((int) emptyCue * cardSize.Width, 8 * cardSize.Height);
            return new Rectangle(origin, cardSize);
        }
    }
}
